DISTRIBUTED PROCESSING NETWORK Version 2.0 Copyright (c)1993 David Bellchambers All rights reserved. TABLE OF CONTENTS 1. INTRODUCTION 1.1 What Is DPN? 1.2 Why Would I Need It? 1.3 System Requirements 1.4 What Do DPN Programs Look Like? 1.5 Program Data Exchange 1.6 So Why Choose DPN? 1.7 What Software Is Available? 1.8 Starting From Nothing 2. INSTALLATION 3. PREPARING FOR DPN 3.1 The NETDRIVE Environment Variable 3.2 The NETTIME Environment Variable 4. USING REMOTE HOSTS 4.1 Starting A Remote Host 4.2 Stopping A Remote Host 4.3 Running A Remote Host Under Windows 5. WRITING APPLICATIONS FOR DPN 5.1 The Turbo Pascal Library 5.1.1 The Constructor Method 5.1.2 The Finished Method 5.1.3 The Kill Method 5.1.4 The ErrorCode Method 5.1.5 The ExitCode Method 5.1.6 The Destructor Method 5.1.7 Global Functions 5.2 The Turbo C++ Library 5.2.1 The Constructor Method 5.2.2 The Finished Method 5.2.3 The Kill Method 5.2.4 The ErrorCode Method 5.2.5 The ExitCode Method 5.2.6 The Destructor Method 5.2.7 Global Functions 5.3 DPN Error Codes 6. DEBUGGING HOST PROGRAMS 7. SPOOLING BATCH PROGRAMS AND DOS COMMANDS 8. DPN SYSTEM MAINTENANCE 8.1 Tidying The Shared Disk 8.2 The TASKS Utility 9. BUILDING A CHEAP NODE 10. DPN IS SHAREWARE 10.1 How To Contact The Author 11. DISCLAIMER 12. USEFUL ADDRESSES 13. ACKNOWLEDGEMENTS 1. INTRODUCTION 1.1 What Is DPN? DPN stands for Distributed Processing Network. It's a way of increasing the effective computing power of a networked PC by allowing it to share it's workload among any number of other PC's on the same network. The programs can be your own, or those of others that have been written to run under DPN. The software included in this package provides everything you need to set up and run the parallel processing network, and also to write your own programs in C++ or object-oriented Pascal to take advantage of the facilities it offers. 1.2 Why Would I Need It? If you are writing programs which do anything computationally intensive or work on large amounts of data, your programs may take a long time to run, even if you have one of the better performing processors. DPN allows you to make the most of your available computing resources to cut processing time to a minimum. It's also virtually transparent to the user. DPN programs are run just like any other, except they can run considerably faster. DPN is at its most effective with tasks which require a large amount of data to be processed according to established routines. Number-crunching is a speciality of DPN which makes it ideal for science and engineering, data analysis, statistics, mathematical research, complex graphics, collating large databases, even artificial intelligence. Any application which involves heavy data manipulation is ideal for DPN. As an example, say you are working on a graphical rendering program which produces screen images from complex 3D model data. By itself your computer might take 20 minutes to generate a single screen picture, but by using DPN to do the work on two computers, the task takes only 10 minutes! 1.3 System Requirements DPN works by transferring programs and data from a client machine to one or more host machines, or nodes, via a network. The one essential requirement for DPN is that all of the computers you want to use in this way must be able to access a common disk drive - a floppy or hard disk drive which can be read from and written to by any other computer on the network. This feature can be provided by a client-server network or a peer-to-peer network. DPN will will even work using serial port networking software as is often used with laptops. Again here, the fundamental requirement is that the network software allows a remote drive on another machine to be accessed as if it was a local drive, while not affecting normal operation of the remote machine. The computers on the network can be of any specification, from a basic PC with 256K, upwards. If you intend to run existing DPN-aware programs on the network, then there are no further requirements. If you intend using the libraries supplied in this package to write your own parallel-processing programs, then you will also require either Borland Turbo Pascal (version 5.5 or higher) or Borland Turbo C++ (version 2.0 or higher), or any compiler which is 100% module-compatible (.TPU/.OBJ) with them. 1.4 What Do DPN Programs Look Like? First and foremost, DPN cannot work with just ANY software. You can't use it to speed up Windows, accelerate Lotus 1-2-3, or perform a faster spell-check within Word Perfect for example. Programs which are to take advantage of the parallel-processing facilities of DPN must be written specifically to include these features. This makes it especially suited to research or specialist environments. You are probably used to the idea of running a single, large program which does all of the work on a single processor. This "serial" processing is precisely why you have to wait so long for your results. DPN uses the principle of breaking down a large program into smaller sub-programs which can be run on many processors simultaneously. If you are used to the idea of programs having functions and procedures then DPN is very similar, as instead of calling a function somewhere within a large program, DPN executes the function in the form of an external program, and because it is an external DOS program it can be run independently on another machine. Consider the example of the graphic rendering program given earlier. The main program (the "client") may have a line that goes something like this: CreateImage(Model); to call the function that creates the full-screen image from the data structure referred to by 'Model'. In DPN, it would look something like this: Image.Init('CREATE.EXE',''); { Pascal } or Task Image("CREATE.EXE",""); // C++ That is virtually all there is to it. CREATE.EXE is the functional sub-program which computes the image (the "host" program). "Image" is an object variable of a pre-defined type which contains all of the information needed to execute the task through DPN. The code written in to the DPN libraries will pass the process to a waiting pool, and will be duly processed by the next host processor to become idle. Your client program can then get on and do something else while the host sub-program runs on another machine. If there is nothing more to do until the results become available, you can use the lines: While Not Image.Finished Do; { Pascal } or while (!Image.Finished()); // C++ to wait until the task is complete. In fact, there is nothing to stop you from starting a number of remote processes, quitting the main program to do something else, and then run another program to work on the results which have become available in the meantime. At this point you may be wondering what could be the advantage of the example given above. Haven't we just let one machine stand idle while exactly the same job has been done by another machine? Surely this would run even more slowly, with all of the overhead of transferring files and running programs remotely? Well yes, but consider these slightly more involved examples: Image.Init('CREATE.EXE','UPPER'); { Pascal } CreateImage('LOWER'); Task Image("CREATE.EXE","UPPER"); // C++ CreateImage("LOWER"); Here we have spooled the CREATE.EXE sub-program to run remotely on another machine, passing it the parameter 'UPPER'. Then we execute an internal routine, passing it the parameter 'LOWER'. The internal function and the host program perform exactly the same task, and indeed, much of the source code will be identical. The string UPPER has been passed to the host program as a command line parameter telling it which part of the screen display to work on. It has been assumed that the remote program knows in which file to look for the 3D data required to create the image. The important point to note is that the CreateImage function running on the local machine will only take half the usual execution time because it's only working on producing half of the screen. By the time it has finished, the remote process will have also completed rendering the other half of the screen and the resultant data file can be loaded. The code to retrieve the results might look like this: Display_Lower_Screen; While Not Image.Finished Do; { Pascal } Display_Upper_Screen; Display_Lower_Screen(); while (!Image.Finished()); // C++ Display_Upper_Screen(); The same end result, but in approximately half the time! By now you should be getting a feel for how DPN can help you to make the most of a limited resource. If the task could be distributed over a whole network of machines, with each machine working on a small portion of the image, it would only take a fraction of the original time, even allowing for the data transfer overhead. 1.5 Program Data Exchange In conventional programs, functions are called with arguments to pass the data they require. DPN allows arguments to be passed to host sub-programs through the command line interface as with conventional DOS programs. While this is useful for telling the host program what it must do, it is no good for transferring large amounts of data. DPN has to use a different approach as once a host program is running on a remote machine it cannot access the data of the client. DPN requires that data is passed between processes in the form of data files stored on a shared disk area. This data must be stored in a format which is mutually understood by both the client and the host programs. For programs which work with huge amounts of data, this data is probably already being stored in disk files instead of memory. 1.6 So Why Choose DPN? It is true that there are many alternative ways of executing several programs at once on a single PC. A good example is the Windows graphical environment, which allows you to create multiple virtual DOS machines when operating in enhanced mode. However, although this allows you to execute several programs at once, the work is still only being done by one micro- processor. Run two programs simultaneously, and the time- slicing employed by the system means that each program runs at half speed. You might as well run the two programs consecutively at full speed, or even keep it as a complete stand-alone program - the overall execution time will be the same. The same may also be said of any other (single- processor) multi-tasking operating system, such as Unix or OS/2. DPN allows you to utilise the power of the PC's already available to you and to maximise their potential, no matter how modest your system. 1.7 What Software Is Available? At present there is very little software available that takes advantage of DPN. The market for such software is small and specialised, and the emphasis is on programmers who need to make use of DPN to come up with the applications. Read on to learn how easy it is to port your existing source code to take full advantage of the benefits of DPN. The author is keen to establish a library of public domain and shareware programs for DPN, and would be delighted to offer assistance to registered users who are writing software. 1.8 Starting From Nothing Due to the number and nature of the various PC networking systems that are available, it has to be assumed that the reader already has access to an established network installed between two or more PC's, and that they are able to share a drive or directory on one of the machines. If this is not the case then there are a variety of networking options open to you, depending largely on how much money you want to spend. DPN was written for those users who need more processing power but cannot afford to spend large amounts of cash, and was therefore designed to be effective on the most minimal of systems. DPN is so simple and effective that you may even wish to dedicate one or more machines to do nothing else but perform the tasks required by other, less powerful machines. As you will see later (section 9, Building A Cheap Node), dedicated machines offer a considerable cost advantage if you are setting a system up from scratch or wish to add more power at minimum cost. Networks come in two basic flavours; "client-server" and "peer-to-peer". With a client-server system, a large, powerful computer acts as a central file store and transfers files to client machines on request via the network. This is the fastest solution but is also the most expensive as one machine is tied up as a dedicated file-server, and the software licence fees are not cheap. Maintenance of the network is also a non-trivial matter and certainly not for the novice. A much cheaper alternative is a peer-to-peer network where each machine makes its local drives and devices available to other machines on a voluntary basis. This solution offers generally slower performance as each machine, in addition to executing user programs, will also from time to time find itself accessing its local devices to transfer data to a another machine. There are a number of very sophisticated peer-to-peer networks available, all of which involve installing networking hardware and software into each computer. The cost of this method of networking is typically around œ150 (at time of writing) for each machine on the network. For the ultimate in low-cost networking you could try a software-only package such as $25 Network. This system uses the existing serial ports to network up to three computers (i.e. a client machine + two remote nodes). The system is slow compared to other systems, but at approximately œ30 for the whole network (including cables) it represents fantastic value for money. DPN was developed using $25 Network and it remains in everyday use on the authors own system. 2. INSTALLATION Once your network is up and running, installation of DPN is straightforward. You will first need to ensure that the drive which is to hold the installed directory will be accessible to all of the other machines on the network. This is important, as some networks allow restricted access to certain drives and/or sub-directories and it is essential that all machines have unrestricted read/write access to the installed DPN directory and any sub-directories that may be created beneath it. The distribution disk contains all of the files required to get a working DPN system up and running. You should have available the following files: REMOTE.EXE creates node capable of executing tasks from other machines REMOTE.ICO a Windows icon for REMOTE.EXE DPN.TPU Turbo Pascal unit for use in DPN programs DPN.HPP C++ header file DPN_T.OBJ C++ object code - tiny model DPN_S.OBJ C++ object code - small model DPN_C.OBJ C++ object code - compact model DPN_M.OBJ C++ object code - medium model DPN_L.OBJ C++ object code - large model DPN_H.OBJ C++ object code - huge model DPN.TXT this documentation INSTALL.EXE the installation program TASKS.EXE a task pool monitor NOTHING.EXE a do-nothing testing program DPN_TEST.PAS a demonstration Pascal program DPN_TEST.CPP a demonstration C++ program DPN_TEST.EXE an executable version REGISTER.TXT a software registration form README.1ST last minute additions to the manual Insert the distribution disk into a floppy disk drive and type: A:INSTALL or B:INSTALL When the program has loaded you will be presented with the installation box which contains all of the options available when installing. Use the mouse to select items within the box, or if you don't have a mouse you can use the 'Tab' key to move around. Pressing the 'Return' key has the same effect as clicking on the 'Install' button. 1. Use the "Language" checkboxes to select which libraries you wish to install. By default, both the C++ and Pascal libraries will be installed. Checking both boxes off will only install the basic DPN system without any language libraries. 2. Use the "From drive" radio buttons to select the drive which contains the installation disk. By default this will be set to the drive where the installation program was run from. 3. Type the name of the DPN directory at the input line labelled "To path". The default setting is C:\DPN. Remember that when the system is up and running, all machines on the network must be able to access this drive and directory, although the local name may differ between machines. 4. Click on the "OK" button (or press 'Return') when you are happy with your selection, or click on the "Cancel" button (or press 'Escape') to exit from the installation process. Once the files have been copied you have the option of having the installation program modify the AUTOEXEC.BAT file to include the NETTIME and NETDRIVE environment variables. These are described fully in section 3 below. For now you can accept the default value for NETTIME and change it later if required. Before making any changes to AUTOEXEC.BAT, the existing copy is renamed as AUTOEXEC.DPN to allow the old copy to be restored if required. 3. PREPARING FOR DPN Preparing the system for DPN requires that each machine connected to the network which is to be used in this way has two DOS environment variables set. These should be set independently for each machine and therefore is ideally done by the AUTOEXEC.BAT file when the machine is switched on. These variables are necessary even if the machine is to be used as a client rather than a host, so they must always be available. The variables are: NETDRIVE and NETTIME 3.1 The NETDRIVE Environment Variable NETDRIVE points to the drive and directory where the DPN system has been installed. It should not contain a trailing '\' character unless it is the root directory. Remember that NETDRIVE should point to the local name of the shared drive for the machine on which it is declared, as not all machines on the network may refer to the shared directory with the same drive letter, i.e. while one machine may be able to access it as E:\DPN, to another machine it may be F:\DPN. NETDRIVE should always be set for the specific machine on which it is declared. If NETDRIVE points to an invalid drive or directory the node will not be able to raise itself onto the DPN system. Examples of valid NETDRIVE assignments are: SET NETDRIVE=E:\DPN SET NETDRIVE=N:\ETC\SHARED\DPN 3.2 The NETTIME Environment Variable NETTIME is a value used by the machine whenever it attempts to access the shared directory. It is the number of seconds the remote computer will wait between successive disk accesses when looking for a task to execute. In other words, if a remote host is idle and waiting for a task, it will look every NETTIME seconds to see if there is a task pending. The value assigned to NETTIME is important to the overall performance of the system. If DPN is running on a client/server network then a value in the range 1-5 is recommended, depending on the normal level of network usage. This is because frequent accessing of the DPN directory on the file-server is unlikely to slow the system significantly and means that remote processes can be started almost immediately after they have been posted. If DPN is operating on a peer-to-peer network where there is no dedicated file-server, then a higher value of NETTIME should be used, typically 5-10 seconds or even more. The value needs to be higher for a peer-to-peer network as the continuous access of shared drives slows down the computer which owns the shared drive while it services the request. For a peer-to-peer network you can see that there is a trade-off between slowing the network down, and having to wait many seconds for a process to get started. This "start-up time" is an important consideration when writing DPN programs. Is that time overhead going to make it worthwhile to create the remote process in the first place? If the task is so brief as to make this a concern, then the answer is almost certainly 'No'. This is an inevitable compromise of using peer-to-peer networks but one that is worth accepting considering the cost advantages. It is suggested that you start with the typical values given here, and fine-tune to a more optimal value after some experience has been gained of using the DPN system. 4. USING REMOTE HOSTS A remote host (or remote processor) is the term for any PC which is running the remote processor program REMOTE.EXE. It is these machines which will be performing the hard work; picking jobs up as they become available, running them and returning the results for the client to retrieve. 4.1 Starting A Remote Host Once the environment variables have been set, a host computer can be activated by typing: REMOTE at the command prompt, where is the local name of the shared DPN directory. If you cannot remember the path from a particular node, type: SET and use the value which is displays as being assigned to NETDRIVE. If you are running REMOTE.EXE from within a batch file then you can use the following to automatically find the REMOTE.EXE program by using the path assigned to NETDRIVE: %NETDRIVE%REMOTE You have the option to override the default values of the environment variables when starting REMOTE.EXE: REMOTE [ NETDRIVE= ] [ NETTIME=xx ] but this should rarely be necessary. If all goes well the computer will produce a banner declaring that it is now on-line. If any problems are detected, the REMOTE program will abort with an error message explaining the problem. The most likely errors to occur at this stage are environment variables not being correctly set (see section 3 above) or the node was unable to find the DPN directory. When a client machine has a task it wants to spool to a remote host for processing, it places a special task file in a sub- directory of NETDRIVE called TASKS. This is the global "pool" where all tasks are sent to be picked up. When a remote node is ready to accept another task it looks to the TASKS sub-directory and pulls out the next available task file, which it reads and performs the action specified. When the node has completed one task it looks for the next. If there are no tasks immediately available, it waits for a while (the time specified by the environment variable NETTIME) and then looks again. This process will continue until the user interrupts the remote processor, or the remote processor detects the occurrence of a fatal error. The remote processor maintains a continuously updated display of the tasks it is running, together with information about any non-fatal errors encountered. During setting up and initialisation of a new system this can be helpful in ensuring that the remote processor functioning correctly and picking up tasks from client nodes. 4.2 Stopping A Remote Host Machines which are running REMOTE.EXE are dedicated to processing remote tasks and may not be used for anything else (although see the following section "Running A Host Under Windows"). If you no longer want to keep a particular node on-line and would like to use the machine for something else, then taking a node off the system and returning it to normal use is simple. Press any key on the keyboard, and when the currently processing task has been completed REMOTE.EXE will terminate and the computer will be returned to its normal function. However it may be a while before the node is returned to normal service while it completes the current task. It must be stressed that the method above is the only proper way to remove a node from the DPN network. Any other interruption (such as a Ctrl-Alt-Del reset, or pressing the reset switch) will destroy the current task and leave the client machine unaware that the job has been lost. This will cause it to wait indefinitely for the task to complete, unless the user has written a routine to avoid this by timing the remote task. All other hosts on the network will be unaffected and will continue to pull new tasks out of the pool and process them, but the process that was running on the off- lined machine will be lost completely. As DPN hosts are so easy to disable, you may wish to consider disconnecting the keyboard or even isolating the node machine in a separate room or cupboard if you are concerned about the security of running tasks, particularly for lengthy program runs. This precaution can only be a deterrent to to clumsy or inquisitive fingers. Due to the open nature of DPN and the architecture of the PC it can never be truly secure. 4.3 Running A Remote Host Under Windows REMOTE.EXE is a standard DOS program and will run quite happily in a DOS session under Microsoft Windows and can even be run in the background as a minimised icon. This may sometimes be desirable as it allows use of a machine even while it is processing tasks spooled by other users. Setting up REMOTE.EXE to run smoothly under Windows is quite simple if you are already familiar with Windows. You will need to create a Program Interface File (.PIF extension) using the PIF Editor supplied with Windows. Set this file up to run REMOTE.EXE in the DPN directory. Ensure that the 'Background Execution' box is checked 'on'. You may, if you wish, alter the processing time offered to this window by selecting the appropriate 'Advanced Settings' options. Once completed, insert this PIF file as a program item in one of your desktop groups. The item will default to an MS-DOS icon, which you may change using the File|Properties option from the main menu. An alternative icon (REMOTE.ICO) has been supplied on the distribution disk. You can also use this opportunity to select the 'Run Minimized' option so that the processor does not clutter the screen. To run the remote processor, simply double-click on it's icon. To halt the remote processor, double-click on the minimised icon which will be somewhere near the bottom of your desktop, and when the window has been restored and is the active window, press any key. This will halt the remote processor and close the window. For a more detailed explanation of starting and stopping the remote processor the reader is referred to sections 4.1 and 4.2 above. Running the remote processor under Windows can have major advantages for the user who has a number of machines available but to which exclusive use of any cannot be guaranteed. You can put the remote processor program item into the Startup group, thereby ensuring that it is always running, although the remote processor will need to be shut down in the usual way before the Windows session can be closed. If the remote processor is running on a very powerful PC (a 486DX say) it is unlikely that performance will be greatly affected by the presence of the remote processor and the user of the host machine may not even be aware that their machine is being used by other other users to run their programs. On slower or busier machines however, both the Windows user and the owner of the process being served will notice a degradation in performance. It is even possible to run multiple instances of REMOTE.EXE on the same machine using two or more separate DOS sessions. While it is perfectly feasible for a single computer to perform the role of several independent remote nodes using this method, it is recommended that this only be attempted with faster machines. This method can also be useful, as you could run several instances of REMOTE.EXE on a single machine, and then run your application on top of them in the fore- ground. Here all of the work would be done transparently on the one machine, although the benefits of using DPN would be totally negated. This does, however, offer an alternative to the user who needs to run DPN-dependent software, but only has one available PC. 5. WRITING APPLICATIONS FOR DPN The first stage in writing any program which will lend itself to parallel processing is to break your program down into modules so that you can see exactly where the processing is most intensive. This will usually be evident from inspection although a utility known as a 'profiler' can be useful, informing you of which functions take the longest to execute. These processing-intensive procedures need to be converted into stand-alone sub-programs so that they can be called by the main program and spooled to a host for execution. Consider this simple program: MAIN ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Input Data ³ ÀÄÄÄÄÄÂÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÁÄÄÄÄÄÄÄ¿ ³ Process Data ³ ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÁÄÄÄÄÄÄ¿ ³ Output Data ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙ In this example, the process which will take the most computing time is the 'Process Data' stage. The code which makes up this stage needs to be rewritten as a stand-alone program which performs the same task. The following figure illustrates the process: MAIN ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Input Data ³ ÀÄÄÄÄÄÂÄÄÄÄÄÄÙ PROCESS ÚÄÄÄÄÄÄÁÄÄÄÄÄÄÄ¿ ---->---- ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Call PROCESS ³ ³ Process Data ³ ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ ----<---- ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÁÄÄÄÄÄÄ¿ ³ Output Data ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙ As well as being fundamental to the operation of DPN, the concept of separating processor intensive tasks into stand- alone programs means a high degree of modularity in your finished programs. In the same way that you combine frequently used functions into units or libraries for use again and again, the existence of a stand-alone program to perform a given task means that the same sub-program can be used by any DPN program. Once you have completed a sub-program to perform, for example, matrix operations, the same sub-program can be called by any DPN program that requires the use of matrices. Actually re-coding your procedures and functions into separate programs is not as difficult as it might at first sound. If you have followed good structured programming methods then you will find that most of your functions can be converted into sub-programs almost on a "cut & paste" approach. While this stand-alone capability is essential it does present a problem when it comes to exchanging data between your main program and a sub-program. In conventional programs you might pass a pointer to a huge array which stores the matrix in some pre- determined format. Simply passing a pointer to a sub-program will not work as the machines are not able to share the same memory space. The solution is to have all data to be passed to a sub-program written to a transfer file in the shared directory. The format of this transfer file must be common to both the client program and the host sub-program. The first task of the sub-program then, is to retrieve this data into it's own memory before starting the process. When the process is complete, the sub-program writes the results back to a transfer file and when the main program is ready, it can read the results back. The process now looks something like the diagram on the next page. MAIN PROCESS ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Input Data ³ - - >>- - ÀÄÄÄÄÄÂÄÄÄÄÄÄÙ / \ ÚÄÄÄÄÄÁÄÄÄÄÄÄ¿ / ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ Write Data ³ / ³ Read Data ³ ÀÄÄÄÄÄÂÄÄÄÄÄÄÙ / ÀÄÄÄÄÄÂÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÁÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÁÄÄÄÄÄÄÄ¿ ³ Call PROCESS ³ ³ Process Data ³ ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÂÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÁÄÄÄÄÄÄ¿ \ ÚÄÄÄÄÄÁÄÄÄÄÄÄ¿ ³ Read Data ³ \ ³ Write Data ³ ÀÄÄÄÄÄÂÄÄÄÄÄÄÙ \ ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ ÚÄÄÄÄÄÄÁÄÄÄÄÄÄÄ¿ \ / ³ Output Data ³ - - <<- - ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ This requirement of reading and writing data files is probably the biggest drawback to modifying existing programs to use DPN, although you may already be using disk files to store large amounts of data in a well-established format (such as .DBF database files) and the few extra lines of code required to exchange the data are a small price to pay. The sub- program, although using transfer files to read and write data, may also be supplied with command line parameters just like any DOS program. This is extremely useful as it allows the sub-programs to receive any number of operational commands together with the all important names of the transfer files. It can even be used to transfer single variables to the sub- program. An example of a sub-program command line execution with parameters might look like this: MATRIX 3RD.MAT PRODUCT 1ST.MAT 2ND.MAT This example informs the sub-program MATRIX.EXE that the input data resides in the files 1ST.MAT and 2ND.MAT, that a product operation should be performed on the two matrices, and that the results are to be stored in the file 3RD.MAT, for retrieval by the main program. So sub-programs are virtually identical to the functions they replace within the main program. The only thing to be borne in mind is that all data must be passed to and from sub- programs using data files, and that all operators and filenames, and other parameters you need to pass to the sub- program must be done through the command line parameter interface. Another important point regarding sub-programs is that they should not request any user data from the keyboard, not even 'Press any key to continue' type prompts. The whole concept of the sub-program is that it should be stand-alone and can run unsupervised. Ideally it should not provide for any screen output either. It may be running on any one of a number of nodes on a network and it should make its presence invisible. Pass it the data it requires, leave it to get on with the job, then pick up the results as they become available. Sub-programs can return a single integer error code to the client program which may be used to check for errors. This is built into the DPN library and is explained later. As an aside, you can see that the example given above has been passed an operator to tell the program what to do with the data it reads in. It is sometimes worth making a sub-program perform a variety of related tasks, in this case matrix operations, as it allows flexibility in future work, and means that you don't have to write a separate program for each operation. Conversely, you may want to separately code the functions in order to minimise the size of the sub-program. The choice is yours. DPN takes advantage of the object-oriented extensions to Turbo Pascal and C++ to make the transition to using DPN as easy as possible. The execution of remote tasks centres around a pre- defined "process object" and its associated methods. This process object is defined in the file DPN.TPU (Pascal) and DPN.HPP (C++) supplied. The Pascal and C++ libraries are described separately in the sub-sections below. 5.1 The Pascal Library In order to make use of the DPN library, your main program will require the line: Uses DPN; somewhere at the start. Remember, it is only the main program executing on the client machine that needs to be DPN aware. This unit and its functions are not required within the remotely executed sub-programs unless you intend to have them also spool tasks for processing by other nodes. The DPN.TPU file was compiled with the far call ($F compiler directive) and overlay code ($O directive) turned on. The process definition object is defined in DPN.TPU as: Type TaskPtr = ^Task; Task = Object Constructor Init(Prog,Params:String); Destructor Done; Virtual; Function Finished:Boolean; Function ExitCode:Integer; Function ErrorCode:Integer; Function Kill:Integer; Private ProgName, ProgParms, JobName:String; ExitValue, ErrorValue:Integer; End; A single instance of the Task object is used to keep track of the progress of a single remote task. Instances of the process object are created in the usual way to any other local or global variable: Var Image:Task; Multiple instantiations of the Task object must be created if you wish to spool more than one remote task at any one time. 5.1.1 The Constructor Method Having declared the instance of the process object, it must be initialised using the Init constructor method. The constructor takes just two parameters. The first parameter is the name of the sub-program that you want to execute remotely. This must include the full path to the sub-program and must also specify an .EXE or .COM extension. Spooling batch files (.BAT extension) is also possible, but requires a slightly different approach which is described in a later section. Since batch programs are usually short programs which execute quickly, it is unlikely that you would ever need to spool one as a remote process, although it can have its uses. It is important to remember that every remote node on the network must be able to locate the sub-program and the data transfer files based on the drive/directory information you supply. This is similar to the concept of the shared drive mentioned earlier, where each node must be able to find the DPN sub-directory if the system is to work. The path of the sub-program must be identical for all the available nodes. For example, if you specified: MyTask.Init('C:\APPS\3D\CREATE.EXE',''); then it is vital that all the remote nodes can find this file by this name. This is because (unless you only have one remote node) you can never be exactly sure which host may pick up the process. If a host receives an instruction to run a program it cannot find the executable file for, it will ignore the process. This will include process filenames which do not specify a .EXE or .COM extension. The second parameter passed to the constructor method is a string containing the command line parameters you wish to pass to the sub-program. This is a single string with a maximum length of 255 characters. Usually it will contain the names of the data transfer files being used to pass data. If this is so then it is important to note that the same conditions on drive and path name apply as for the name of the executable sub-program. All the available nodes must be able to find the drive and directory as specified to it if it is to be able to load the data and process the task. If it cannot find the data, your sub-programs may crash with a "file not found" error. You may find it useful to use the DOS SUBST or ASSIGN commands to create a 'pseudo-drive', whereby all your DPN applications and sub-programs appear to be on the same drive/directory to all the available nodes if this cannot be directly implemented in the network. The constructor method therefore performs all of the work required to spool the task to a remote host. When an task is initialised using the constructor, it is placed in the task pool and will be picked up for processing by the next host to become free. Once the process has been spooled to a host, the information contained within the instance of the Task object is your only link to the running process. If the Task object instance is destroyed within the client program then the remote process can no longer be traced. It will still execute on a remote host in due course and return results as normal, but the client program will be unable to determine the status of the process and it will have effectively been forgotten. The process object allows the client program to determine when the remote process has been completed, and to retrieve the exit code and error code of the remote process on completion. If you no longer need to keep track of the remote process then you may destroy the Task object, and even re-allocate it with another process, but the original task definition will then be lost. This is also the case if the declared object goes out of scope during execution of the client program. If you retain the process instance for the lifetime of the task, then there are a number of additional Task object methods which are available for monitoring the spooled process which are detailed below. It is important to remember that Turbo Pascal does not call the constructor method of an object at the time of declaration. The object is declared in the "var" statement, and then has to be explicitly initialised using the constructor. This means that it is possible to create a task object and then perform operations on the task before it has been initialised with any meaningful values. This must be avoided at all costs as the results will be unpredictable and also totally meaningless. This can be partly circumvented by the use of dynamically allocated objects: Var MyTask:TaskPtr; Begin ... MyTask:=New(TaskPtr,Init(Prog,Params)); ... In this example, declaring MyTask does not create an instance of the Task object, merely a pointer to one. The function New creates a dynamically allocated instance of the Task object, automatically calling the constructor method with the supplied parameters. While this does offer a partial solution, it still remains the responsibility of the programmer to ensure that the pointer variable MyTask has been assigned before attempting to de-reference it. The same restrictions on the scope of the pointer also apply as for real instances of any variable. 5.1.2 The Finished Method The Finished method provides a means of determining if a remote process has been completed and returns a boolean value of 'true' or 'false', i.e. If Image.Finished Then ..... Finished will return false only if it is evident that the task is still not completed. Any error encountered by the method, such as the total disappearance of the task will cause it to return 'true', returning the appropriate error code to the task object. This ensures that any "waiting" code is exited before the error code needs to be inspected. 5.1.3 The Kill Method The Kill method allows a remote process to be terminated before it can be executed by a remote host. Result:=MyTask.Kill; This will erase the task definition file from the task pool. Note that the Kill procedure can only stop jobs which are still pending and have not been started. Once a job has been picked up by a node and is running, it cannot be interrupted short of resetting the node, and this is not recommended. Kill returns a boolean value to indicate the success of the operation. It will return 'true' if the task was successfully killed or if it had already completed, and 'false' for all other events. If a call to this method does return 'false', the error code should be inspected to reveal the cause of the failure. Kill has no effect if you attempt to kill a process that has either been completed or killed previously. 5.1.3 The ErrorCode Method ErrorCode returns the integer DPN error code of the last DPN operation performed on this task. Remember that because Task is an object, each instance of the object has it's own, built- in error code which is totally independent of all other instances of the object. The value of the error code is not affected by examining it's value in this way, and an adverse value will not affect any subsequent DPN operations. Possible error codes are described in a later section. An example of the function in use is: Result:=MyTask.ErrorCode; 5.1.4 The ExitCode Method The ExitCode function returns the integer value returned by the completed sub-program on termination. This value is read automatically when the Finished method returns a true value, and is the only valid way to access this result. The exit code can be very useful, as it can be used by sub-programs to indicate errors encountered during execution, as opposed to attempting to retrieve them from data files. The exit code will not always be that supplied by the terminating sub- program. If a system error occurs that is not trapped by the sub-program, such as a 'file not found' error, then this will cause the sub-program to terminate unexpectedly. This method allows investigation of such errors. An example of the function in use is: Result:=MyTask.ExitCode; 5.1.5 The Destructor Method The final method included within the object definition is the destructor method. This method is called when the task is completed or no longer needs to be monitored, and the Task object is being disposed. It performs essential clean-up after the task, which mainly involves deleting any files created during the creation and spooling of the task. Pascal users need to call this method explicitly: MyTask.Done; or Dispose(MyTaskPtr,Done); { dynamic objects } 5.1.6 Global Functions In addition to the task object definition, there are five global functions which are not used in conjunction with a task but provide general DPN functions: Function DPN_Pending:Word; Procedure DPN_Pause; Function DPN_NetDrive:String; Function DPN_NetTime:Word; Function DPN_ErrorMsg(Code:Integer):String; DPN_Pending is a function which returns the total number of processes waiting in the task pool. It does not include any tasks which are currently running. DPN_Pause is a procedure that waits the number of seconds specified by the NETTIME environment variable. This can be very useful and in some cases highly desirable. On a peer-to-peer network, where disk accesses cause the throughput of computing to be reduced, the code: Repeat Until MyTask.Finished; would cause the system to access the shared drive continuously, looking to see if the process had been complete. On a network such as $25 Network this would cause unacceptable slowness and the system may even appear to 'hang'. Far better then to use: While Not MyTask.Finished Do DPN_Pause; The value of NETTIME set for this procedure will have a significant bearing on the overall performance of any DPN system based on a peer-to-peer network. The reader is referred to the earlier section on setting the environment variables for more information. The function DPN_NetTime returns the integer number of seconds which have been assigned to the NETTIME environment variable, while DPN_NetDrive returns a string containing the NETDRIVE environment variable. The last global DPN function is DPN_ErrorMsg. This is a procedure which returns an error message string based on the value of the error code supplied. The messages returned are described in section 5.3 below. 5.2 The C++ Library In order to make use of the DPN library, your program will require the line: #include somewhere near the start, or if you have not copied the header file to the INCLUDE files sub-directory of your compiler: #include "C:\DPN\DPN.HPP" or wherever you have installed the DPN software. During the linking stage you will also need to link in the appropriate object file (.OBJ extension) for the memory model you are using. There is an object file for each of the six memory models, identified with the following file names: DPN_T.OBJ tiny model DPN_S.OBJ small model DPN_M.OBJ medium model DPN_C.OBJ compact model DPN_L.OBJ large model DPN_H.OBJ huge model All of the object files were compiled under Turbo C++ version 2.0, with the overlay code option turned on. Remember, it is only the main program executing on the client machine that needs to be DPN aware. This unit and its functions are not required within the remotely executed sub-programs unless you intend to have them also spool tasks for processing by other nodes. The definition of the process object is described below: class Task { int ErrorValue,ExitValue; char ProgName[255],ProgParms[255],JobName[255]; public: Task(char *Prog,char *Params); virtual ~Task(void); int Finished(void); int ExitCode(void); int ErrorCode(void); int Kill(void); }; A single instance of the Task object is used to keep track of the progress of a single remote task. Instances of the process object are created in the usual way to any other local or global variable: { Task MyTask(Prog,Params); ... The parameter supplied as arguments to the definition of MyTask are passed automatically to the constructor method as the object is defined. Multiple instantiations of the Task object must be created if you wish to spool more than one remote task at any one time. 5.1.1 The Constructor Method The constructor method is called automatically in C++ whenever an instance of an object is defined, or a dynamic object is allocated. The constructor takes just two parameters. The first parameter is the name of the sub-program that you want to execute remotely. This must include the full path to the sub-program and must also specify an .EXE or .COM extension. Spooling batch files (.BAT extension) is also possible, but requires a slightly different approach which is described in a later section. Since batch programs are usually short programs which execute quickly, it is unlikely that you would ever need to spool one as a remote process, although it can have its uses. It is important to remember that every remote node on the network must be able to locate the sub-program and the data transfer files based on the drive/directory information you supply. This is similar to the concept of the shared drive mentioned earlier, where each node must be able to find the DPN sub-directory if the system is to work. The path of the sub-program must be identical for all the available nodes. For example, if you specified: Task MyTask("C:\\APPS\\3D\\CREATE.EXE",""); then it is vital that all the remote nodes can find this file by this name. This is because (unless you only have one remote node) you can never be exactly sure which host may pick up the process. If a host receives an instruction to run a program it cannot find the executable file for, it will ignore the process. This will include process filenames which do not specify a .EXE or .COM extension. The second parameter passed to the constructor method is a string containing the command line parameters you wish to pass to the sub-program. This is a single string with a maximum length of 255 characters. Usually it will contain the names of the data transfer files being used to pass data. If this is so then it is important to note that the same conditions on drive and path name apply as for the name of the executable sub-program. All the available nodes must be able to find the drive and directory as specified to it if it is to be able to load the data and process the task. If it cannot find the data, your sub-programs may crash with a "file not found" error. You may find it useful to use the DOS SUBST or ASSIGN commands to create a 'pseudo-drive', whereby all your DPN applications and sub-programs appear to be on the same drive/directory to all the available nodes if this cannot be directly implemented in the network. The constructor method performs all of the work required to spool the task to a remote host. When a task is initialised the constructor is called automatically and the task is placed in the task pool and will be picked up for processing by the next host to become free. Once the process has been spooled to a host, the information contained within the instance of the Task object is your only link to the running process. If the Task object instance is destroyed within the client program then the remote process can no longer be traced. It will still execute on a remote host in due course and return results as normal, but the client program will be unable to determine the status of the process and it will have effectively been forgotten. The process object allows the client program to determine when the remote process has been completed, and to retrieve the exit code and error code of the remote process on completion. If you no longer need to keep track of the remote process then you may destroy the Task object, and even re-allocate it with another process, but the original task definition will then be lost. This is also the case if the declared object goes out of scope during execution of the client program. If you retain the process instance for the lifetime of the task, then there are a number of additional Task object methods which are available for monitoring the spooled process which are detailed below. Instances of the task object may also be dynamically allocated. This can be very useful, as often on entering a function code block the exact parameters to be supplied to the constructor are not known and therefore the object cannot be defined. Dynamically allocated instances allow this to be circumvented: { Task *MyTask; ... MyTask=new Task(Prog,Params); ... Here, declaring MyTask does not create an instance of the Task object, merely a pointer to one. The operator 'new' creates a dynamically allocated instance of the Task object, automatically calling the constructor method with the supplied parameters. It is the responsibility of the programmer to ensure that the pointer variable MyTask has been assigned before attempting to de-reference it. The same restrictions on the scope of the pointer also apply as for real instances of any variable. 5.1.2 The Finished Method The Finished method provides a means of determining if a remote process has been completed and returns an integer value indicating the success: if (MyTask.Finished()) { .... } Finished will return a value of 0 only if it is evident that the task is still not completed. Any error encountered by the method, such as the total disappearance of the task will cause it to return a value of 1, returning the appropriate error code to the task object. This ensures that any "waiting" code is exited before the error code needs to be inspected. 5.1.3 The Kill Method The Kill method allows a remote process to be terminated before it can be executed by a remote host. Result=MyTask.Kill(); Note that the Kill procedure can only stop jobs which are still pending and have not been started. Once a job has been picked up by a node and is running, it cannot be interrupted short of resetting the node, and this is not recommended. Kill returns an integer value to indicate the success of the operation. It will return 0 if the task was successfully killed or if it had already completed, and returns 1 for all other events. If a call to this method does return 1, the error code should be inspected to reveal the cause of the failure. Kill has no effect if you attempt to kill a process that has either been completed or killed previously. 5.1.3 The ErrorCode Method ErrorCode returns the integer DPN error code of the last DPN operation performed on this task. Remember that because Task is an object, each instance of the object has it's own, built- in error code which is totally independent of all other instances of the object. The value of the error code is not affected by examining it's value in this way, and an adverse value will not affect any subsequent DPN operations. Possible error codes are described in a later section. An example of the function in use is: Result=MyTask.ErrorCode(); 5.1.4 The ExitCode Method The ExitCode function returns the integer value returned by the completed sub-program on termination. This value is read automatically when the Finished method returns a true value, and is the only valid way to access this result. The exit code can be very useful, as it can be used by sub-programs to indicate errors encountered during execution, as opposed to attempting to retrieve them from data files. The exit code will not always be that supplied by the terminating sub- program. If a system error occurs that is not trapped by the sub-program, such as a 'file not found' error, then this will cause the sub-program to terminate unexpectedly. This method allows investigation of such errors. An example is: Result=MyTask.ExitCode(); 5.1.5 The Destructor Method The final method included within the object definition is the destructor method. This method is called implicitly by the program when the task object passes out of the scope of the program unit in which it is declared, or when a dynamically allocated instance of the Task object is disposed. It performs essential clean-up after the task, which mainly involves deleting any files created during the spooling of the task. 5.1.6 Global Functions In addition to the task object definition, there are five global functions which are not used in conjunction with a task but provide general DPN functions: void DPN_Initialise(void); void DPN_Pause(void); void DPN_NetDrive(char *Dest); char *DPN_ErrorMsg(int Code,char *Dest); int DPN_NetTime(void); unsigned int DPN_Pending(void); DPN_Initialise is a very important function. It must be called before any other DPN functions are used. This function provides vital setting up for the DPN system. The function need only be used once, preferably somewhere near the start of your program. DPN_Pending is a function which returns the total number of processes waiting in the task pool. It does not include any tasks which are currently running. DPN_Pause is a procedure that waits the number of seconds specified by the NETTIME environment variable. This can be very useful and in some cases highly desirable. On a peer-to-peer network, where disk accesses cause the throughput of computing to be reduced, the code: while (!MyTask.Finished()); would cause the system to access the shared drive continuously, looking to see if the process had been complete. On a network such as $25 Network this would cause unacceptable slowness and the system may even appear to 'hang'. Far better then to use: while (!MyTask.Finished()) DPN_Pause(); The value of NETTIME set for this procedure will have a significant bearing on the overall performance of any DPN system based on a peer-to-peer network. The reader is referred to the earlier section on setting the environment variables for more information. The function DPN_NetTime returns the integer number of seconds which have been assigned to the NETTIME environment variable, while DPN_NetDrive returns a string containing the NETDRIVE environment variable. The last global DPN function is DPN_ErrorMsg. This is a function which returns an error message string into the string 'Dest' based on the value of the error code supplied. The function returns a pointer to 'Dest'. The messages returned are described below. 5.3 DPN Error Codes Value Meaning ----- ------- 0 No errors encountered -1 Task file has disappeared -2 TASKS sub-directory in NETDRIVE has been lost -3 Task is still running -4 Error reading/writing to task file -99 Non-specific error 6. DEBUGGING HOST PROGRAMS The fact that the remote sub-programs are stand-alone and do not provide for any user input means that you can find yourself with a problem if a process crashes or returns unpredicted results. The only solution here is extensive testing and debugging before using the sub-programs in any application and include as much error-trapping as possible so that your sub-programs are bullet-proof. As mentioned above, version 2.0 of DPN allows sub-programs to return an integer error code directly to the client program which spooled them, in addition to the returning data files which the sub-programs create. An advantage of writing your own sub-programs is that they can be written and tested in your existing programming environment. Test data files can be created and your sub-program single-stepped (with watches set on variables if required) and the program debugged in the usual manner. Once everything is running smoothly, you will have the confidence to use that sub-program in any other projects which require it's features - one of the major benefits of such a modular approach (as with any programming). 7. SPOOLING BATCH PROGRAMS AND DOS COMMANDS DPN was designed to be effective with large numerical programs which would benefit from parallel processing to reduce their execution times. In the rare event that you might want to spool a batch file or a DOS command to a node as a remote process instead of a .EXE or .COM file, a slightly different approach is required to that described above, as in order to execute the command the system requires a copy of the command line interpreter COMMAND.COM. This has to be specified in the task definition as the name of the remote process. The name of the batch file is passed to COMMAND.COM as a command line parameter. This example shows how you would execute the batch file C:\ETC\SILLY.BAT : { Pascal } Silly.Init('C:\COMMAND.COM','/C C:\ETC\SILLY.BAT'); // C++ Task Silly("C:\\COMMAND.COM","/C C:\\ETC\\SILLY.BAT"); As with spooling any other task, you should ensure that the path and name of the command line interpreter is the same on all machines, unless you know you will be executing the task on one specific machine. For those familiar with the Borland language libraries, the function 'getenv' can be used to get the name and path of the command line interpreter from the system environment variables, but beware! The function 'getenv' is evaluated before the process is spooled, and as a result the command line interpreter will have the drive and path of the client machine, not the node on which the task will be running. Use 'getenv' only if you are sure that the command line interpreter is the same on all your machines. If all machines have booted from a hard disk drive C: or a floppy disk drive A: then this will probably be the case, but where machines have booted from a mixture of floppy and hard disk drives, problems may be encountered. Alternatively, put a copy of COMMAND.COM in the shared DPN directory. The '/C' parameter in front of the batch file name tells the interpreter that when the batch file has been completed, the command interpreter should unload itself and return control to the original version of COMMAND.COM. Without it, your remote host will freeze when the task has been completed. The same system should be employed for any internal DOS commands that are to be executed remotely, i.e.: { Pascal } DosTask.Task('C:\COMMAND.COM','/C COPY A:\*.* C:\'); // C++ Task DosTask("C:\\COMMAND.COM","/C COPY A:\\*.* C:\\"); External DOS commands can be spooled using the conventional technique as they are external programs and do not require the presence of COMMAND.COM to run. 8. DPN SYSTEM MAINTENANCE The DPN system is basically self-maintaining if the procedures and practices described here are followed. After prolonged and extensive periods of use you may find that the system begins to slow down. The extensive disk usage of DPN means that the shared DPN drive may become fragmented as multiple files are created and destroyed. You may also find that 'rogue' files can get left behind in the DPN directory. Sometimes these are task files which were not cleaned up properly by the client program, but more often they are user created data files. In normal usage this will cause no problems, but if a degradation in performance becomes apparent the solution is very straight-forward. 8.1 Tidying The Hard Disk First of all ensure that there are no user tasks which are waiting to be completed using the utility TASKS.EXE described below, and take all of the nodes off line using the methods described in section 4. When the shutdown process is complete, type: DEL \TASKS where NETDRIVE is the shared DPN drive/directory. If you cannot remember where this is, type: SET and use the value defined in the environment variables. When the display responds with: All files in sub-directory will be lost! Proceed? (Y/N) type 'Y' and the task pool will be flushed clean. At this point, you may wish to consider using a disk defragmenting program, such as Norton Utilities' SPEEDISK, in order to compress the disk down and linearise the available disk space. 8.2 The TASKS Utility Included on the software distribution disk is a utility program called TASKS.EXE. This program provides the functionality of the DPN function 'DPN_Pending' in a DOS program by informing of the number of tasks which are still waiting to be picked up by a remote processor. TASKS.EXE goes one step further, and also informs of the number of tasks which are presently flagged as running, and also the number of completed jobs which are waiting to be picked up by their client programs. It is often these latter files which begin to crowd the task pool when client programs do not look after their tasks properly. To run TASKS.EXE, simply type: TASKS at the DOS prompt and press return. TASKS excepts no command line parameters, except for '/?' which acts as a help switch. 9. BUILDING A CHEAP NODE By now you should have a good understanding of DPN and, hopefully, will be thinking about preparing your applications to take advantage of it. DPN has always been intended for use on an established network, but if you are starting from a very small system and funds are limited (and aren't they always?) then this section will show you how to establish a simple yet highly effective DPN network, if you are prepared to do a little work with a screwdriver. The basic premise is that a remote host requires very little hardware to stand alone as a dedicated number crunching machine. A working node can be set up for use with $25 Network using the following components: 1. Case inc. PSU 2. Motherboard inc. RAM 3. Floppy disk drive (1.44Mb) 4. Floppy disk controller card 5. Serial interface card 6. $25 Network If you wish to connect the node into a more sophisticated network you will also need a network adaptor card. You can see what a minimalist system it is, with no provision for screen output (nodes don't really need it) and no hard disk drive. While the latter may be useful for working with large quantities of data, the author's experience of using the system has shown that it is easier to keep all programs and data in a shared directory on the client machine. As you will recall, it is very important that when spooling a remote task, the filename of the task program is the same on ALL of the nodes. This is essential as the user may never be sure which node will pick up the task. At time of writing, the components required to build a minimal node could be bought new for a total cost of less than œ100, not including the motherboard. This means that the balance can be spent on ensuring that you have the best processor for the task. You could consider fitting a maths co-processor for faster number-crunching (up to ten times faster), or maybe install extra memory to create a super-fast RAM disk for working on those large data files. The 'plug-together' approach of DPN means that you can add extra nodes whenever you like providing you have the basic knowledge required to assemble a PC yourself and connect it to your network. The cost savings can be enormous over buying a complete machines with monitors, hard disks and keyboards that never get used. There is great scope for expansion too. The configuration described above is virtually identical to the authors own system which was used to develop DPN. Considerable cost savings were also made by using the $25 Network software instead of implementing one of the other systems of peer-to-peer networking. This software-based network allows up to three machines to shares resources by using the serial ports to transfer data between machines. It is certainly very much slower than conventional networks, but is also extremely effective and reliable. The address of the UK distributor is listed at the end of this file. If you do not wish to use the $25 Network software, which allows only two nodes to be attached to the client and with rather slow disk access, then you will need to consider one of the peer-to-peer networks. In addition to the software drivers which must be loaded, these also require the presence of a dedicated network interface card, although the speed of the network is significantly increased. For the configuration described above which does not include a hard disk drive, you will need to create a bootable floppy disk. This is done in the usual way using the DOS FORMAT command: FORMAT A: /S Once this disk has been initialised, create any necessary CONFIG.SYS and AUTOEXEC.BAT start-up files on the disk. Be sure to include the DPN environment variables in the AUTOEXEC.BAT file. The CONFIG.SYS file will probably need to contain the network software drivers. You will find that both of these files need only be minimal in what they load, as the dedicated host does not need to load keyboard drivers or set the DOS prompt, etc. As an example, the AUTOEXEC.BAT file in the authors own dedicated node looks like this: NET$25 COM1 SHARE:A { network software } SET NETDRIVE=C:\DPN { the shared drive } SET NETTIME=15 { slow for peer-peer } :WAITING { wait for network } IF NOT EXIST %NETDRIVE%\REMOTE.EXE GOTO WAITING %NETDRIVE%\REMOTE { start processing } The same single boot disk can be used to start up each host machine. When the host is closed down it will attempt to read from the floppy drive to complete execution of the AUTOEXEC file causing a drive error. This is unimportant as there are no more commands to execute, and if a dedicated node has been off-lined then it is probably about to be powered down too. 10. DPN IS SHAREWARE The DPN software included on this distribution disk is shareware. This means that it is a fully-fledged version of the software with nothing omitted. You are free to make as many copies of the software as you like and you may distribute them freely, providing that they are distributed as the complete set of files. If required the files may be compressed into an archive file for distribution. This file should be called DPN.xxx, where xxx is the suffix used by the archiving software. The copyright in this software remains the property of the author at all times. If you use DPN and find it useful you are required to register your use of the software with the author within 30 days. Registration costs just œ15 for installation on a single network of unlimited size and provides the following benefits: - a version of the software with the shareware banners disabled - unlimited software support - free upgrades as they become available Cheques should be sent to the author at the address below, together with the name of the registered user, your company/university/institution (if applicable), and your full postal address. The file REGISTER.DOC on the distribution disk contains a suitable registration form which may be printed out. 10.1 How To Contact The Author Unfortunately I am not in a position to be able to offer telephone support at time of writing. However, I would be delighted to answer postal queries from registered users on receipt of a stamped, self-addressed envelope. Enquiries and registrations should be sent to: David Bellchambers 7, Croftlands Avenue, Stubbington, Fareham, Hampshire PO14 2JR When writing in with a problem, please include a disk or listing of all the relevant files, including node AUTOEXEC.BAT files, the DPN program listing itself, and any other information you can provide on your DPN installation. I know that getting a system up and running can be a little confusing the first time. I am very interested in compiling a list of DPN-aware software which users are writing and would like to make available to other users. This includes not only complete applications, but also utility sub-programs which perform useful tasks and which other users might like to include in their applications. Your comments on this, and any other aspect of DPN, would be gratefully received. Finally, thank you for taking the time to review this software. I hope it will prove useful to you. 11. DISCLAIMER While very attempt has been made to ensure that this software performs according to the specifications and limitations set out above, the author cannot accept any responsibility for damage or loss of any kind arising from its use. The suitability of this software to any particular task must be determined by, and is the responsibility of, the user. 12. USEFUL ADDRESSES For $25 Network : EQ Consultants Allt an Fhionn, St. Fillians, Perthshire PH6 2NG Tel. (0764) 85220/85225 Fax. (0764) 85241 13. ACKNOWLEDGEMENTS MS-DOS and Windows are trademarks of Microsoft Corporation. IBM PC,XT and OS/2 are trademarks of International Business Machines All other trademarks acknowledged.